
package com.joysuch.wwyt;

import cn.zlg.common.springmvc.validate.DefaultJsonExceptionResponseBodyBuilder;
import cn.zlg.common.springmvc.validate.JsonExceptionResponseBodyBuilder;
import com.joysuch.wwyt.core.common.util.PropertiesHelper;
import com.joysuch.wwyt.core.common.util.PropertiesLoader;
import com.joysuch.wwyt.core.filter.BackSiteFilter;
import com.joysuch.wwyt.core.security.ShiroDbRealm;
import com.joysuch.wwyt.core.security.UserLoginFilter;
import com.joysuch.wwyt.core.security.WwytAuthenticationFilter;
import com.joysuch.wwyt.core.security.WwytLogoutFilter;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.*;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

@Configuration
@Profile({"product","dev","zq"})
public class ShiroConfig {

    public static final String SESSION_ID_NAME_WWYT = "JSESSIONID_WWYT";

    @Primary
    @Bean("properties")
    public Properties properties() throws IOException {
        PropertiesLoader loader = new PropertiesLoader();
        loader.setFileEncoding("UTF-8");
        loader.setValue("classpath:conf.properties");
        Properties properties = loader.createProperties();
        return properties;
    }

    @Bean("propertiesHelper")
    public PropertiesHelper propertiesHelper() throws IOException {
        PropertiesHelper propertiesHelper = new PropertiesHelper();
        propertiesHelper.setProperties(properties());
        return propertiesHelper;
    }

    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean("shiroRealm")
    public Realm shiroRealm() {
        ShiroDbRealm realm = new ShiroDbRealm();
        realm.setAuthorizationCachingEnabled(false);
        return realm;
    }

    @Bean("shiroEhcacheManager")
    public EhCacheManager shiroEhCacheManager() throws IOException {
        EhCacheManager ehCacheManager = new EhCacheManager();
        String cacheManagerConfigFile = properties().getProperty("shiroCacheManagerConfigFile");
        ehCacheManager.setCacheManagerConfigFile(cacheManagerConfigFile);
        // ehCacheManager.setCacheManagerConfigFile("classpath:ehcache/shiro-ehcache.xml");
        return ehCacheManager;
    }

    @Bean(name = "sessionManager")
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        // 设置session过期时间7天
        sessionManager.setGlobalSessionTimeout(7L * 24 * 3600 * 1000L);
        Cookie cookie = new SimpleCookie(SESSION_ID_NAME_WWYT);
        cookie.setHttpOnly(true);
        sessionManager.setSessionIdCookie(cookie);
        return sessionManager;
    }

    @Bean("securityManager")
    public DefaultWebSecurityManager securityManager() throws IOException {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm());
        securityManager.setCacheManager(shiroEhCacheManager());
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    @Bean("shiroFilter")
    @DependsOn("propertiesHelper")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(BeanFactory beanFactory) throws IOException {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager());
        factoryBean.setLoginUrl("/login");
        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
        // TODO 待修复
        filters.put("backSite", new BackSiteFilter(beanFactory));
        filters.put("user", new UserLoginFilter(beanFactory));
        filters.put("authc", new WwytAuthenticationFilter(beanFactory));
        filters.put("logout", new WwytLogoutFilter(beanFactory));
        factoryBean.setFilters(filters);
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/bp/risk/bigScreen/**", "anon");
        filterChainDefinitionMap.put("/doc.html", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/app/*.jpg", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/image/**", "anon");
        filterChainDefinitionMap.put("/doLogin", "anon");
        filterChainDefinitionMap.put("/login/loginBycode","anon");
        filterChainDefinitionMap.put("/bp/enterprise/companyList", "anon");
        filterChainDefinitionMap.put("/bp/enterprise/loginType", "anon");
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/bp/app/download", "anon");
        filterChainDefinitionMap.put("/base/user/getPwdBack", "anon");
        filterChainDefinitionMap.put("/base/user/auditPwd", "anon");
        filterChainDefinitionMap.put("/base/user/editPwd", "anon");
        filterChainDefinitionMap.put("/image/view/**", "anon");
        filterChainDefinitionMap.put("/mhMonitorPointAndType/getsimulationData/READ","anon");
        filterChainDefinitionMap.put("/mh/customize-monitoring/point/push", "anon");
        filterChainDefinitionMap.put("/mhMonitorPointAndType/windVane/detail", "anon");
        // 对外 api 接口
        filterChainDefinitionMap.put("/api/v1/**", "anon");

        //新版流程引擎
        filterChainDefinitionMap.put("/api/base/config/**", "anon");
        filterChainDefinitionMap.put("/api/base/point/**", "anon");
        filterChainDefinitionMap.put("/api/base/video/**", "anon");
        filterChainDefinitionMap.put("/api/base/location-verify/**", "anon");
        filterChainDefinitionMap.put("/api/base/certificate/**", "anon");
        filterChainDefinitionMap.put("/api/base/menu/**", "anon");
        filterChainDefinitionMap.put("/api/base/user/**", "anon");
        filterChainDefinitionMap.put("/api/base/depart/**", "anon");
        filterChainDefinitionMap.put("/api/base/job/**", "anon");
        filterChainDefinitionMap.put("/api/base/role/**", "anon");
        filterChainDefinitionMap.put("/api/base/district/**", "anon");
        filterChainDefinitionMap.put("/api/base/device/**", "anon");
        filterChainDefinitionMap.put("/api/base/contractor/**", "anon");
        filterChainDefinitionMap.put("/api/base/departcontractor/**", "anon");
        filterChainDefinitionMap.put("/api/base/notify/**", "anon");
        filterChainDefinitionMap.put("/api/base/cascade/**", "anon");
        filterChainDefinitionMap.put("/api/base/screenTabConfig/**", "anon");

        // 积木报表
        filterChainDefinitionMap.put("/report-jimu/**", "anon");
        filterChainDefinitionMap.put("/report-api/**", "anon");
        // 业务流程引擎
        filterChainDefinitionMap.put("/api/alarm-message/**", "anon");
        filterChainDefinitionMap.put("/api/mh/monitorPoint/**", "anon");
        filterChainDefinitionMap.put("/api/token/**", "anon");
        //报警订阅接口
        filterChainDefinitionMap.put("/bp/data-access/getV3AreaAlarm", "anon");
        filterChainDefinitionMap.put("/bp/data-access/getV3jobAlarmEvent", "anon");
        filterChainDefinitionMap.put("/bp/data-access/getV3CarAlarm", "anon");

        // licence
        filterChainDefinitionMap.put("/base/licences/upload", "anon");
        filterChainDefinitionMap.put("/base/licences/tools/**", "anon");
        // APP 登录相关
        filterChainDefinitionMap.put("/doLoginApp", "anon");

        //地图多分厂配置
        filterChainDefinitionMap.put("/wwyt/screen-map-factory-config/list", "anon");
        filterChainDefinitionMap.put("/wwyt/screen-map-factory-config/getBuildingIdByLocation", "anon");

        filterChainDefinitionMap.put("/system-turn/ProcessPage/**", "anon");
        filterChainDefinitionMap.put("/**", "user,backSite");



        factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return factoryBean;
    }

    // 注解生效1
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            org.apache.shiro.mgt.SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public FilterRegistrationBean openEntityManagerInViewFilterRegistrationBean() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new OpenEntityManagerInViewFilter());
        filterRegistration.setEnabled(true);
        filterRegistration.addUrlPatterns("/*");
        return filterRegistration;
    }

    @Bean
    public FilterRegistrationBean shiroFilterRegistrationBean() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
        filterRegistration.setEnabled(true);
        filterRegistration.addInitParameter("targetFilterLifecycle", "true");
        filterRegistration.addUrlPatterns("/*");
        return filterRegistration;
    }

    @Bean
    public JsonExceptionResponseBodyBuilder exceptionReponseBuilder() {
        return new DefaultJsonExceptionResponseBodyBuilder();
    }
}
